package com.bolt.report.engine.export.pdf;

import com.bolt.common.io.IoUtil;
import com.bolt.common.utils.ImageUtil;
import com.bolt.common.utils.StrUtil;
import com.bolt.report.definition.Align;
import com.bolt.report.definition.PaperSize;
import com.bolt.report.definition.PrintOrder;
import com.bolt.report.definition.StyleDefinition;
import com.bolt.report.engine.OutputStreamExporterOutput;
import com.bolt.report.engine.export.AbstractExporter;
import com.bolt.report.engine.model.Cell;
import com.bolt.report.engine.model.Column;
import com.bolt.report.engine.model.PageDetails;
import com.bolt.report.exception.ReportException;
import com.bolt.report.util.StyleUtil;
import com.bolt.report.util.ToolUtil;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;

public abstract class BasePdfExporter extends AbstractExporter<OutputStreamExporterOutput> {

    protected OutputStream outputStream;

    public BasePdfExporter() {
        super();
    }

    public BasePdfExporter(Map<String, Object> parameters) {
        super(parameters);
    }


    protected Document createDocument() {
        float width = reportPrint.getPageWidth(PaperSize.SizeUnit.PT);
        float height = reportPrint.getPageHeight(PaperSize.SizeUnit.PT);
        Rectangle pageSize = new RectangleReadOnly(width, height);
        if (PrintOrder.HORIZONTAL == reportPrint.getPrintOrderValue()) {
            pageSize = pageSize.rotate();
        }
        float leftMargin = ToolUtil.millimetersConvertUnit(reportPrint.getLeftMargin(), PaperSize.SizeUnit.PT);
        float rightMargin = ToolUtil.millimetersConvertUnit(reportPrint.getRightMargin(), PaperSize.SizeUnit.PT);
        float topMargin = ToolUtil.millimetersConvertUnit(reportPrint.getTopMargin(), PaperSize.SizeUnit.PT);
        float bottomMargin = ToolUtil.millimetersConvertUnit(reportPrint.getBottomMargin(), PaperSize.SizeUnit.PT);
        Document document = new Document(pageSize, leftMargin, rightMargin, topMargin, bottomMargin);
        return document;
    }

    public PdfPCell createCell(StyleDefinition cssStyle) {
        PdfPCell cell = new PdfPCell();
        cell.setBorder(Rectangle.NO_BORDER);
        cell.setPadding(0);
        if (StrUtil.isNotBlank(cssStyle.getBgcolor())) {
            int[] rgb = StyleUtil.hexColorToRgb(cssStyle.getBgcolor());
            cell.setBackgroundColor(new BaseColor(Integer.valueOf(rgb[0]), Integer.valueOf(rgb[1]), Integer.valueOf(rgb[2])));
        }
        if (cssStyle.getAlign() != null && cssStyle.getValign() != Align.normal) {
            Align align = cssStyle.getAlign();
            if (align.equals(Align.left)) {
                cell.setHorizontalAlignment(Element.ALIGN_LEFT);
            } else if (align.equals(Align.center)) {
                cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            } else if (align.equals(Align.right)) {
                cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
            }
        }
        if (cssStyle.getValign() != null && cssStyle.getValign() != Align.normal) {
            Align valign = cssStyle.getValign();
            if (valign.equals(valign.top)) {
                cell.setVerticalAlignment(Element.ALIGN_TOP);
            } else if (valign.equals(Align.middle)) {
                cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
            } else if (valign.equals(Align.bottom)) {
                cell.setVerticalAlignment(Element.ALIGN_BOTTOM);
            }
        }
        return cell;
    }


    protected PdfPTable createPdfTable(PageDetails page) throws DocumentException {
        float[] columnWidth = new float[page.getColumn().size()];
        int columnSize = 0;
        float totalWidth = 0;
        for (Column column : page.getColumn()) {
            columnWidth[columnSize] = ToolUtil.pixelToPoint(column.getWidth());
            totalWidth = totalWidth + columnWidth[columnSize];
            columnSize++;
        }
        PdfPTable pdfTable = new PdfPTable(columnSize);
        pdfTable.setLockedWidth(true);
        pdfTable.setTotalWidth(totalWidth);
        pdfTable.setWidths(columnWidth);
        pdfTable.setHorizontalAlignment(Element.ALIGN_LEFT);
        return pdfTable;
    }

    protected Phrase createPdfPhrase(StyleDefinition cssStyle, String text) throws DocumentException, IOException {
        Phrase phrase = new Phrase();
        BaseFont fontChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        Font font = new Font(fontChinese);

        if (cssStyle.getFontSize() != 0) {
            font.setSize(cssStyle.getFontSize());
        }
        int fontStyle = Font.NORMAL;
        if (cssStyle.isBold()) {
            fontStyle = Font.BOLD;
        }
        if (cssStyle.isItalic()) {
            fontStyle = fontStyle | Font.ITALIC;
        }
        if (cssStyle.isStrik()) {
            fontStyle = fontStyle | Font.STRIKETHRU;
        }
        font.setStyle(fontStyle);


        if (StrUtil.isNotBlank(cssStyle.getFontColor())) {
            int[] rgb = StyleUtil.hexColorToRgb(cssStyle.getFontColor());
            font.setColor(rgb[0], rgb[1], rgb[2]);
        }
        phrase.setFont(font);
        phrase.add(text);
        return phrase;
    }

    //
    protected Phrase createPdfPhrase(Cell cell) throws DocumentException, IOException {
        return createPdfPhrase(cell.getStyle(), (String) cell.getElement().getValue());
    }




    protected com.itextpdf.text.Image buildPdfImage(String base64Data, float width, float height) {
        try {
            com.itextpdf.text.Image pdfImg = null;
            InputStream input = ImageUtil.base64DataToInputStream(base64Data);
            try {
                byte[] bytes = IoUtil.readBytes(input);
                pdfImg = com.itextpdf.text.Image.getInstance(bytes);
                float imgWidth = pdfImg.getWidth();
                float imgHeight = pdfImg.getHeight();
                if (width == 0) {
                    width = Float.valueOf(imgWidth).intValue();
                }
                if (height == 0) {
                    height = Float.valueOf(imgHeight).intValue();
                }
                width = ToolUtil.pixelToPoint(width - 2);
                height = ToolUtil.pixelToPoint(height - 2);
                pdfImg.scaleToFit(width, height);
            } finally {
                IoUtil.close(input);
            }
            return pdfImg;
        } catch (Exception ex) {
            throw new ReportException(ex);
        }

    }


}